package com.smt.modules.app.controller;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.google.gson.Gson;
import com.smt.common.enums.Code;
import com.smt.common.enums.EventEnum;
import com.smt.common.utils.*;
import com.smt.common.validator.ValidatorUtils;
import com.smt.modules.app.annotation.Login;
import com.smt.modules.app.annotation.LoginUser;
import com.smt.modules.app.utils.JwtUtils;
import com.smt.modules.bus.entity.*;
import com.smt.modules.bus.service.*;
import com.smt.modules.bus.vo.EmailStreamVo;
import com.smt.modules.bus.vo.StreamVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.bytebuddy.asm.Advice;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.smt.modules.bus.vo.MemberUserVo;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Member;
import java.sql.Time;
import java.util.*;
import java.util.logging.Level;


@RestController
@RequestMapping("/app")
@Api(tags = {"AppUserController"}, description = "成员用户表(客户端接口)")
public class AppUserController {

    @Autowired
    private MemberUserService userService;
    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private GradeService gradeService;
    @Autowired
    private StreamService streamService;
    @Autowired
    private EmailStreamService emailStreamService;
    @Autowired
    private MemberUserService memberUserService;

    @Autowired
    private BillService billService;

    @Autowired
    private LevelTaskService levelTaskService;

    @Autowired
    private InviteService inviteService;
    /**
     * 成员用户登录
     */
    @PostMapping("/login")
    @ApiOperation(value = "/login", notes = "成员用户登录", response = MemberUserVo.class)
    public R login(@RequestBody MemberUserVo memberUserVo, HttpServletResponse response) {
        //表单校验
        ValidatorUtils.validateEntity(memberUserVo);

        //用户登录
        long userId = userService.login(memberUserVo);
        if(userId == 0){
            return R.error(EnumToKeyUtil.toInt(Code.QUERY_DATA_ERROR),"账号或密码错误");
        }else if(userId == -1){
            return R.error(EnumToKeyUtil.toInt(Code.DELETE_DATA_ERROR),"您尚未注册，请前去注册");
        }
        //生成token
        String token = jwtUtils.generateToken(userId);

        Map<String, Object> map = new HashMap<>(16);
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());
        map.put("userId",userId);
        MemberUserEntity memberUserEntity = memberUserService.selectById(userId);
        if(!Objects.isNull(memberUserEntity)){
            map.put("mId",memberUserEntity.getMessageId());
        }else{
            map.put("mId",null);
        }
        //判断用户是否有效
        boolean invalid = isInvalid(response, userId);
        if(invalid){
            //前端带过来的token本地cookie存储
            Cookie cookie = new Cookie("ut", token);
            cookie.setPath("/");
            cookie.setMaxAge(Constant.MINUTE_S * 60 * 12);
            response.addCookie(cookie);
            return R.ok(map);
        }else {
            return R.error(EnumToKeyUtil.toInt(Code.UNKNOWN_ERROR),"登录失败");
        }
    }

    /**
     * 成员用户注册接口
     *
     * @param memberUserVo
     * @return
     */
    @PostMapping("/register")
    @ApiOperation(value = "/register", notes = "成员用户注册接口", response = MemberUserVo.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "email", value = "邮箱", dataType = "String", paramType = "query"),
    })
    public R register(@RequestBody MemberUserVo memberUserVo, HttpServletRequest request) {
        //添加消息id
        String replace = UUID.randomUUID().toString().replace(Constant.FILE_SPILT, "");
        memberUserVo.setMessageId(replace);
        //表单校验
        ValidatorUtils.validateEntity(memberUserVo);
        String code = memberUserVo.getCode();
        int count = 0;
        String mobile = memberUserVo.getMobile();
        String email = memberUserVo.getEmail();
        //短信流水获取验证码
        StreamVo streamVo = streamService.selectOneByMobileNumber(mobile);

        if (null == code || "".equals(code.trim())) {
            return R.error(EnumToKeyUtil.toInt(Code.REQUEST_PARAM_EMPTY),"验证码不能为空");
        } else {
            if(streamVo==null){
                return R.error(EnumToKeyUtil.toInt(Code.REQUEST_PARAM_ERROR),"获取验证码失败");
            }
            String sessionCode = streamVo.getParam();

            if (!StringUtils.contains(sessionCode, code)) {
                return R.error(EnumToKeyUtil.toInt(Code.REQUEST_PARAM_ERROR),"验证码输入错误");
            }
            EntityWrapper<MemberUserEntity> wrapper = new EntityWrapper<>();

            count = memberUserService.selectCount(wrapper.eq("mobile", mobile));
            if (count != 0) {
                return R.error(EnumToKeyUtil.toInt(Code.MODIFY_DATA_ERROR),"用户已经存在");
            }
            MemberUserEntity user = new MemberUserEntity();
            user.setMobile(mobile);
            user.setEmail(email);
            user.setUsername(memberUserVo.getUsername());
            user.setPassword(DigestUtils.sha256Hex(memberUserVo.getPassword()));
            user.setCreateTime(new Date());
            userService.insert(user);
            //创建用户积分
            GradeEntity gradeEntity = new GradeEntity();
            gradeEntity.setMemberId(user.getUserId());
            gradeEntity.setCreateTime(new Date());
            gradeService.insert(gradeEntity);
            //创建用户主线任务
            List<LevelTaskEntity> MainTaskList = levelTaskService.selectList(new EntityWrapper<LevelTaskEntity>()
                    .eq("type", 1));
            MainTaskList.stream().forEach(m -> {
                BillEntity billEntity = new BillEntity();
                billEntity.setIsReward(0);
                billEntity.setTransactionName(user.getMobile());
                billEntity.setExpenditure(1);
                billEntity.setBillTitle(m.getTitle());
                billEntity.setAmount(m.getPointValue());
                billEntity.setBusBusinessId(user.getUserId());
                billEntity.setType(1);
                billService.insert(billEntity);
            });

            //生成当天的奖励任务  后期整合代码
            List<LevelTaskEntity> levelList = levelTaskService.selectList(new EntityWrapper<LevelTaskEntity>()
                    .eq("type", 0));
            levelList.stream().forEach(l -> {
                BillEntity billEntity = new BillEntity();
                if("每天签到".equals(l.getTitle())){
                    billEntity.setIsReward(1);
                }else{
                    billEntity.setIsReward(0);
                }
                billEntity.setType(0);
                billEntity.setBusBusinessId(user.getUserId());
                billEntity.setAmount(l.getPointValue());
                billEntity.setBillTitle(l.getTitle());
                billEntity.setExpenditure(1);
                billEntity.setCreateTime(DateTime.now().toDate());
                billEntity.setTransactionTime(DateTime.now().toDate());
                billEntity.setTransactionName(user.getUsername());
                billService.insert(billEntity);
            });
            //添加邀请对应关系映射
            InviteEntity inviteEntity = new InviteEntity();
            inviteEntity.setToUserContact(mobile);
            inviteService.update(inviteEntity,
                    new EntityWrapper<InviteEntity>()
            .eq("to_user",email));
            return R.ok("注册成功");
        }
    }

    @Login
    @GetMapping("/userInfo")
    @ApiOperation(value = "/userInfo", notes = "获取用户信息")
    public R userInfo(@LoginUser MemberUserEntity user) {
        user.setPassword(null);
        return R.ok().put("user", user);
    }

    @Login
    @GetMapping("/userId")
    @ApiOperation(value = "/userId", notes = "获取用户ID")
    public R userInfo(@RequestAttribute("userId") Integer userId) {
        return R.ok().put("userId", userId);
    }

    /**
     * TODO 测试
     *
     * @return
     */
    @GetMapping("/notToken")
    @ApiOperation(value = "/notToken", notes = "忽略Token验证测试")
    public R notToken() {
        return R.ok().put("msg", "无需token也能访问。。。");
    }


    /**
     * 退出
     */
    @GetMapping("/logout")
    @ApiOperation(value = "/logout", notes = "退出登录")
    public R logout(HttpServletResponse response) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("token")) {
                    cookie = new Cookie("token", null);
                    cookie.setMaxAge(0);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                } else if (cookie.getName().equals("ut")) {
                    cookie = new Cookie("ut", null);
                    cookie.setMaxAge(0);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
        }
        return R.ok();
    }


    /**
     * 找回密码
     *
     * @param memberUserVo
     * @return
     */
    @PostMapping("/findPassWord")
    @ApiOperation(value = "找回密码", httpMethod = "POST")
    public R findPassWord(@RequestBody MemberUserVo memberUserVo, HttpServletRequest request) {
        String code = memberUserVo.getCode();
        boolean flag = false;
        String queryStr = "";
        if (code == null) {
            return R.error(EnumToKeyUtil.toInt(Code.REQUEST_PARAM_EMPTY),"验证码不能为空！");
    }
        String email = memberUserVo.getEmail();
        String mobile = memberUserVo.getMobile();
        if (email != null && CheckUtil.checkEmail(email)) {
            EmailStreamVo emailStreamVo = emailStreamService.selectOneByMobileNumber(email);
            if (StringUtils.contains(emailStreamVo.getCode(),code)) {
                flag = true;
                queryStr = "email";
            }
        } else if (mobile != null && CheckUtil.checkPhone(mobile)) {
            StreamVo streamVo = streamService.selectOneByMobileNumber(mobile);
            if (StringUtils.contains(streamVo.getParam(), code)) {
                flag = true;
                queryStr = "mobile";
            }
        }
        if (flag) {
            //查询用户
            MemberUserEntity queryUser = memberUserService.selectOne(new EntityWrapper<MemberUserEntity>()
                    .eq(queryStr, queryStr.equalsIgnoreCase("mobile") ? mobile : email));
            if (queryUser != null) {
                //修改密码
                MemberUserEntity memberUserEntity = new MemberUserEntity();
                memberUserEntity.setEmail(email);
                memberUserEntity.setMobile(mobile);
                memberUserEntity.setPassword(DigestUtils.sha256Hex(memberUserVo.getPassword()));
                boolean result = memberUserService.update(memberUserEntity, new EntityWrapper<MemberUserEntity>()
                        .eq(queryStr, queryStr.equalsIgnoreCase("mobile") ? mobile : email));
                return result ? R.ok("修改密码正确") : R.error(EnumToKeyUtil.toInt(Code.MODIFY_DATA_ERROR),"密码修改错误");
            } else {
                return R.error(EnumToKeyUtil.toInt(Code.UNKNOWN_ERROR),"用户不存在！");
            }
        }
        return R.error(EnumToKeyUtil.toInt(Code.QUERY_DATA_ERROR),"验证码输入错误！");
    }

    /**
     * 用户信息修改表
     *
     * @param memberUserVo
     * @param memberUserEntity
     * @return
     */
    @Login
    @PostMapping("/edit")
    @ApiOperation(value = "用户信息修改表", httpMethod = "POST")
    public R editUserInfo(@RequestBody MemberUserVo memberUserVo, @LoginUser MemberUserEntity memberUserEntity) {
        return memberUserService.edit(memberUserVo, memberUserEntity);
    }

    /**
     * 判断的的用户是否是有效用户
     *
     * @param response
     * @param userId
     * @return
     */
    private boolean isInvalid(HttpServletResponse response,Long userId){
        MemberUserEntity memberUserEntity = memberUserService.selectById(userId);
        //过期积分判断
        if(!expiredDate(memberUserEntity,response)){
            return false;
        }
        return true;
    }
    /**
     * 判断在注册后的一个月之后积分是否大于1000，小于的话就跳转到积分领取页面
     *
     * @param memberUserEntity
     * @param response
     * @return
     */
    public boolean expiredDate(MemberUserEntity memberUserEntity, HttpServletResponse response) {
        Date createTime = memberUserEntity.getCreateTime();
        DateTime now = DateTime.now();
        int days = Days.daysBetween(new DateTime(createTime), now).getDays();
        EntityWrapper<GradeEntity> gradeEntityEntityWrapper = new EntityWrapper<>();
        Wrapper<GradeEntity> eq = gradeEntityEntityWrapper.setSqlSelect("integral,level")
                .eq("member_id", memberUserEntity.getUserId());
        GradeEntity gradeEntity =
                gradeService.selectOne(eq);
        //获取积分
        Integer integral = gradeEntity.getIntegral();
        //获取等级
        Integer level = gradeEntity.getLevel();
        try {
            if (days + 1 >= Constant.EXPIRED_DATE && integral <= Constant.LEVEL_2) {
                Map map = new HashMap();
                map.put("status",EnumToKeyUtil.toInt(Code.INSIDE_INTERFACE_INVOKE_ERROR));
                map.put("msg","您的使用期限已经到期，请使用积分升级");
                returnJson(response, JSONUtils.toJSONString(map));
                return false;
            } else if(days + 1 >= Constant.EXPIRED_DATE && level < 2){
                Map map = new HashMap();
                map.put("status",EnumToKeyUtil.toInt(Code.OPERATION_SUCCESS));
                map.put("msg","您的积分过低，请先赚取积分");
                returnJson(response, JSONUtils.toJSONString(map));
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 数据返回前端
     *
     * @param response
     * @param returnStr
     */
    private void returnJson(HttpServletResponse response, String returnStr){
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(returnStr);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    /**
     * 获取当前用户id
     *
     *  @deprecated 并入内部方法中
     */
    @Login
    @GetMapping("/getUserId")
    @ApiOperation(value = "获取当前用户id",httpMethod = "GET")
    public R getUserId(@RequestAttribute("userId")long userId){
        return R.ok().put("userId",userId);
    }


    /**
     * 获取用户密码
     *
     *  @deprecated 并入内部方法中
     */
    @Login
    @GetMapping("/getMId")
    @ApiOperation(value = "获取当前用户id",httpMethod = "GET")
    public R setUserS(@RequestAttribute("userId")long userId){
        MemberUserEntity memberUserEntity = memberUserService.selectById(userId);
        String messageId = memberUserEntity.getMessageId();
        return R.ok().put("messageId",messageId);
    }

}
